package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.face.AipFaceTemplate;
import com.itheima.autoconfig.huanxin.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.Log;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserInfo;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import com.itheima.vo.ErrorResult;
import com.itheima.vo.UserInfoVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.sql.Struct;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class UserManager {

    @DubboReference
    private UserService userService;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private UserInfoService userInfoService;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    // 保存用户
    public ResponseEntity save(User user) {
        Long userId = userService.save(user);
        return ResponseEntity.ok(userId); // 响应状态码200，将userId扔到响应体返回
    }

    // 根据手机号，查询用户
    public ResponseEntity findByPhone(String phone) {
        User user = userService.findByPhone(phone);
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(500).body(ErrorResult.error());
        }
        return ResponseEntity.ok(user);
    }

    // 登录、注册时发动的短信验证码
    public void sendSms(String phone) {
        // 1.生成6位随机数
        String smsCode = RandomUtil.randomNumbers(6);
        // 为了方便测试，我这里写成固定的
        smsCode = "123456";

        // 2.调用阿里云发送短信
        //TODO 上线之前将阿里云短信发送开启
        // smsTemplate.sendSms(phone, smsCode);

        // 3.向redis中存储正确验证码   ，今天一定有同学写错 ofMinutes（分钟）  ofMillis（毫秒）
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE + phone, smsCode, Duration.ofMinutes(5));
    }

    // 用户注册登录功能
    public ResponseEntity regAndLogin(String phone, String verificationCode) {
        // 1.取出redis的验证码
        String codeFromRedis = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        // 2.校验是否一致
        if (!StrUtil.equals(verificationCode, codeFromRedis)) {
            return ResponseEntity.status(500).body(ErrorResult.loginError());
        }
        // 3.根据手机号查询用户
        User user = userService.findByPhone(phone);
        boolean isNew;
        String type;
        if (user == null) { // 3-1 新用户
            isNew = true;
            user = new User();
            user.setPhone(phone);
            user.setPassword("123456");

            Long userId = userService.save(user);
            user.setId(userId);

            // 向环信注册此用户
            huanXinTemplate.register(userId);

            type = "0102"; // 新用户

        } else { // 老用户
            isNew = false;

            type = "0101"; // 老用户
        }
        // 4.制作token
        user.setPassword(null);
        Map<String, Object> claims = BeanUtil.beanToMap(user);
        String token = JwtUtil.createToken(claims);

        // 5.设置token有效期，7天
        String json = JSON.toJSONString(user);
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token, json, Duration.ofDays(7));

        // 发送日志消息
        // 1-1 准备消息
        Log log = new Log();
        log.setUserId(user.getId()); // 操作人id
        log.setLogTime(DateUtil.formatDate(new Date())); // 操作时间
        log.setPlace("三里屯"); // 操作地点
        log.setEquipment("大华为"); //操作设备
        log.setType(type); // 操作类型
        // 1-2 发送消息
        rocketMQTemplate.convertAndSend("tanhua-user-log", log);

        // 6.返回结果
        Map<String, Object> responseMap = new HashMap<>();
        responseMap.put("isNew", isNew);
        responseMap.put("token", token);

        return ResponseEntity.ok(responseMap);
    }

    // 保存用户基本信息
    public void saveUserInfoBase(UserInfo userInfo, String token) {
        // 1.根据token获取user对象
        User user = findUserByToken(token);
        // 2.将userId设置到userInfo中
        userInfo.setId(user.getId());
        // 3.调用rpc保存
        userInfoService.save(userInfo);

    }

    // 抽取根据token获取user对象
    public User findUserByToken(String token) {

        // 根据token查询redis
        String json = stringRedisTemplate.opsForValue().get(ConstantUtil.USER_TOKEN + token);
        // 空值处理
        if (StrUtil.isEmpty(json)) {
            return null;
        }
        // 将json转为user对象
        User user = JSON.parseObject(json, User.class);

        // 续期redis
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token, json, Duration.ofDays(7));

        return user;
    }

    // 保存用户头像信息
    public ResponseEntity saveUserInfoHead(MultipartFile headPhoto, String token) throws IOException {
        // 1.根据token获取user对象
        User user = findUserByToken(token);
        // 2.检查此图片是否为人脸
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect) {
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }
        // 3.将图片存储到oss
        String picUrl = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        // 4.封装userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(picUrl); // 头像
        userInfo.setCoverPic(picUrl); // 封面
        // 5.调用rpc完成userInfo更新
        userInfoService.update(userInfo);

        return ResponseEntity.ok(null);
    }

    // 查询用户信息
    public ResponseEntity findUserInfoVo(Long userId) {
        // 1.调用rpc查询
        UserInfo userInfo = userInfoService.findById(userId);
        // 2.将结果封装vo
        UserInfoVo vo = new UserInfoVo();
        BeanUtil.copyProperties(userInfo, vo);
        // 单独设置age
        if (userInfo.getAge() != null) {
            vo.setAge(userInfo.getAge().toString());
        }
        // 3.返回vo
        return ResponseEntity.ok(vo);
    }

    // 修改用户基本信息
    public void updateUserInfoBase(UserInfo userInfo) {
        // 1.获取线程内user对象
        User user = UserHolder.get();
        // 2.设置userId到userInfo中
        userInfo.setId(user.getId());
        // 3.调用rpc更新
        userInfoService.update(userInfo);
    }
}
